# ~*~ coding: utf-8 ~*~

import time

from flask import current_app

from apps.common.dbbase import BaseModel
from apps.common.utils import generate_uuid
from apps.extensions import db
from ..utils.connectivity import Connectivity
from .user import AdminUser

__all__ = ['Asset', 'AssetNode']


class Asset(BaseModel):
    __tablename__ = 'assets_asset'

    PLATFORM_LINUX = 'Linux'
    PROTOCOL_SSH = 'ssh'

    id = db.Column(db.CHAR(36), default=generate_uuid, primary_key=True)
    hostname = db.Column(db.VARCHAR(128), unique=True)
    manage_ip = db.Column(db.VARCHAR(32))
    public_ip = db.Column(db.String(32), nullable=True)
    port = db.Column(db.Integer, default=22)
    protocol = db.Column(db.VARCHAR(128), default=PROTOCOL_SSH)
    platform = db.Column(db.VARCHAR(128), default=PLATFORM_LINUX)

    # Auth
    admin_user_id = db.Column(db.CHAR(36), nullable=True)

    # Collect
    vendor = db.Column(db.VARCHAR(64), nullable=True)
    model = db.Column(db.VARCHAR(64), nullable=True)
    sn = db.Column(db.VARCHAR(128), nullable=True)

    cpu_model = db.Column(db.VARCHAR(128), nullable=True)
    cpu_count = db.Column(db.Integer, nullable=True)
    cpu_cores = db.Column(db.Integer, nullable=True)
    cpu_vcpus = db.Column(db.Integer, nullable=True)
    memory = db.Column(db.String(64), nullable=True)
    disk_total = db.Column(db.VARCHAR(1024), nullable=True)
    disk_info = db.Column(db.VARCHAR(1024), nullable=True)

    os = db.Column(db.VARCHAR(128), nullable=True)
    os_version = db.Column(db.VARCHAR(16), nullable=True)
    os_arch = db.Column(db.VARCHAR(16), nullable=True)
    hostname_raw = db.Column(db.VARCHAR(128), nullable=True)

    # Other
    create_by = db.Column(db.VARCHAR(32), nullable=True)
    create_time = db.Column(db.INT, default=time.time)
    update_time = db.Column(db.INT, default=time.time, onupdate=time.time)

    def is_windows(self):
        if self.platform in ("Windows", "Windows2016"):
            return True
        else:
            return False

    def is_unixlike(self):
        if self.platform not in ("Windows", "Windows2016", "Other"):
            return True
        else:
            return False

    def is_support_ansible(self):
        return self.has_protocol('ssh') and self.platform not in ("Other",)

    @property
    def cpu_info(self):
        info = ""
        if self.cpu_model:
            info += self.cpu_model
        if self.cpu_count and self.cpu_cores:
            info += "{}*{}".format(self.cpu_count, self.cpu_cores)
        return info

    @property
    def hardware_info(self):
        if self.cpu_count:
            return '{} Core {} {}'.format(
                self.cpu_vcpus or self.cpu_count * self.cpu_cores,
                self.memory, self.disk_total
            )
        else:
            return ''

    @property
    def connectivity(self):
        if not self.admin_user_id:
            return Connectivity.unknown()
        admin_user = AdminUser.query.get(self.admin_user_id)
        if admin_user:
            connectivity = admin_user.get_asset_connectivity(self)
            current_app.logger.debug('get asset connectivity: {}'.format(connectivity.display()))
            return connectivity
        else:
            return Connectivity.unreachable()

    @connectivity.setter
    def connectivity(self, value):
        if not self.admin_user_id:
            return
        current_app.logger.debug('set asset connectivity: {}'.format(value))
        admin_user = AdminUser.query.get(self.admin_user_id)
        if admin_user:
            admin_user.set_asset_connectivity(self, value)

    def __str__(self):
        return "<Asset: {}>".format(self.hostname)


class AssetNode(BaseModel):
    __tablename__ = 'assets_asset-node'

    id = db.Column(db.CHAR(36), default=generate_uuid, primary_key=True)
    asset_id = db.Column(db.CHAR(36), default=generate_uuid, primary_key=True)
    node_id = db.Column(db.CHAR(36), default=generate_uuid, primary_key=True)
